//
// Created by LiuYou on 2021/7/23.
//

#include "HasPtrLikePtrUsePointer.hpp"


//ResourceManagement::HasPtrLikePtrUsePointer::HasPtrLikePtrUsePointer(std::string* ptrString, int defaultValue, size_t* referenceCount)
//        : ptrString( ptrString ), defaultValue( defaultValue ), referenceCount( referenceCount ) {}


ResourceManagement::HasPtrLikePtrUsePointer::HasPtrLikePtrUsePointer(const std::string& hasPtrLikePtr) :
        ptrString( new std::string( hasPtrLikePtr )), defaultValue( 0 ), referenceCount( new std::size_t( 1 )) {}

ResourceManagement::HasPtrLikePtrUsePointer::~HasPtrLikePtrUsePointer() {
    //<editor-fold desc="书上的版本">
//    if (--*referenceCount == 0) {
//        delete ptrString;
//        delete referenceCount;
//    }
    //</editor-fold>

    //<editor-fold desc="我写的版本, 比较容易理解">
    if (--(*referenceCount) == 0) {
        delete ptrString;
        delete referenceCount;
    }
    //</editor-fold>
}

ResourceManagement::HasPtrLikePtrUsePointer::HasPtrLikePtrUsePointer(
        const ResourceManagement::HasPtrLikePtrUsePointer& rhs) :
        ptrString( rhs.ptrString ), defaultValue( rhs.defaultValue ), referenceCount( rhs.referenceCount ) {
    /// \brief 拷贝构造, 两个对象的引用计数都要加1。而赋值就不是了, 赋值操作是赋值运算符(=)右侧引用加1, 而左侧的引用减1, 注意: ! 这里的
    /// 的减1并不是对当前的引用的资源的引用计数减一, 而是对之前引用的资源计数减1。因为=左边管理了其它资源, 并不再管理之前的资源。
    ///
    /// 因为这两个对象都引用了这些资源。当一个对象不再引用这些资源的时候或者去引用其它资源的时候, 引用计数减一。因为此时只有一个对象引用之前的
    /// 资源了。
    ///
    /// 注意: ! 从引用计数去看对象。而不要从对象去看引用计数！
    ++*referenceCount;

}

//ResourceManagement::HasPtrLikePtrUsePointer&
//ResourceManagement::HasPtrLikePtrUsePointer::operator=(const ResourceManagement::HasPtrLikePtrUsePointer& rhs) {
//    // 这里的if判断是我自己加的, 很有必要。
//    if (&rhs == this) {
//        return *this;
//    }
//
//    //<editor-fold desc="书上的版本">
////    ++*rhs.referenceCount;
////    if (--*referenceCount == 0) {
////        delete ptrString;
////        delete referenceCount;
////    }
//    //</editor-fold>
//
//    //<editor-fold desc="我写的版本">
//    /// \brief =右边的对象的资源的引用计数加1。注意: ! 引用计数是对资源的引用计数, 即多少个对象在管理这些资源！
//    ++(*rhs.referenceCount);
//    /// \brief =左侧的对象的资源的引用计数减1, 并必须与0进行判断, 因为无法确定赋值运算之前=左侧的对象的引用计数是否为1,
//    /// 如果为1的话, 那么这次的赋值运算结束后, 左侧对象的引用计数就变成0了。需要释放资源。
//    /// 而这个对象新的引用计数是对新的资源的引用计数, 与之前的资源的引用计数再也没有任何关系！
//    if (--(*referenceCount) == 0) {
//        delete ptrString;
//        delete referenceCount;
//    }
//    //</editor-fold>
//
//    ptrString = rhs.ptrString;
//    defaultValue = rhs.defaultValue;
//    referenceCount = rhs.referenceCount;
//    return *this;
//}

size_t* ResourceManagement::HasPtrLikePtrUsePointer::getReferenceCount() const {
    return referenceCount;
}


/// \brief 拷贝并交换这项技术的有趣指出是它自动处理了自我赋值情况且天然就是异常安全的。
/// \param rhs
/// \return
ResourceManagement::HasPtrLikePtrUsePointer&
ResourceManagement::HasPtrLikePtrUsePointer::operator=(ResourceManagement::HasPtrLikePtrUsePointer rhs) {
    swap( *this, rhs );
    return *this;
}
